#ifndef GUI_H
#define GUI_H

#include "solver.h"
#include "undoredo.h"

#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Box.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Round_Button.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Color_Chooser.H>
#include <FL/Fl_Slider.H>
#include <FL/Fl_Int_Input.H>
#include <FL/Fl_Float_Input.H>

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace std;
using namespace cv;

const int MAX_FILENAME_SIZE = 2000;

enum PointerType {
	PTR_INIT=0,
	PTR_PEN=1,
	PTR_ERASER=2
};

enum ImageType {
	IMAGE_INPUT=1,
	IMAGE_MASK=2,
	IMAGE_OUTPUT=4
};

class MainWindow {

	public:

		MainWindow();
		~MainWindow();

		Fl_Window	*m_window_mainWindow;
		Fl_Menu_Bar	*m_menuBar;
		Fl_Box		*m_box_title;
		Fl_Button	*m_button_colors[26],
					*m_button_current;
		Fl_Slider	*m_slider_inputMagnifier,
					*m_slider_maskMagnifier,
					*m_slider_outputMagnifier,
					*m_slider_radius;

		Fl_Int_Input	*m_input_radius,
						*m_input_inputMagnifier,
						*m_input_maskMagnifier,
						*m_input_outputMagnifier;

		Fl_Color_Chooser *m_colorChooser;

		Mat	*m_inputImage,
			*m_outputImage,
			*m_mask;

		Solver *m_solver;
		
		ActionList *m_actionList;

		Color m_color;

		char	m_inputName[MAX_FILENAME_SIZE],
				m_maskName[MAX_FILENAME_SIZE],
				m_outputName[MAX_FILENAME_SIZE];

		int m_radius;

		int m_fastColorize,
			m_lastMaskModified,
			m_lastMaskSaved;

		int m_mouse_leftDown,
			m_mouse_rightDown,
			m_mouse_posX,
			m_mouse_posY,
			m_key_flag;

		int m_pointerType;

		int	m_inputMagnifier,
			m_maskMagnifier,
			m_outputMagnifier;

		void show();

		int clearImage(int type);
		int saveImage(const Mat *img);
		int loadImage(const char *path, int isInputImage );
		int askToSaveImage(const char *msg, const Mat *img);
		int askToSaveImages(int type);
		int initializeMask();
		int showCanvas(int type);
		
		ActionBlock *setMatColor(Mat &m, int x, int y, int r);
		ActionBlock *setMatColor(Mat &m, Mat &p_input, int x, int y, int r);
		ActionBlock *getMatColor(Mat &m, int x, int y, int r);
		Color getMatColor(Mat &m, int x, int y);
		int doAction(Mat &m, const ActionBlock *p);

		char *getInputName();
		char *setInputName(const char *p_inputName);
		char *getMaskName();
		char *setMaskName(const char *p_maskName);
		char *getOutputName();
		char *setOutputName(const char *p_outputName);

		Color getColor();
		int setColor(double p_r, double p_g, double p_b);
		int getRadius();
		int getRadius2();
		int setRadius(int r);

		int setColorButton(Fl_Button *o);
		Fl_Button *getColorButton();
		int setOnly(Fl_Button *o);

		int setMagnifier(int p_factor, int type);
		int getMagnifier(int type);

		int setMouseLeftDown();
		int setMouseRightDown();
		int setMouseLeftRelease();
		int setMouseRightRelease();
		int isMouseLeftDown();
		int isMouseRightDown();

		int getMouseX();
		int getMouseY();
		int setMouse(int x, int y);
		int setMouseX(int x);
		int setMouseY(int y);
		int isMouseMoved(int x, int y);

		int getKeyFlag();
		int setKeyFlag(int flag);
		int isCtrlDown();
		int isShiftDown();
		int isAltDown();
		int isKeyDown();
		int isMouseDown();

		int setLastMaskModified(int p);
		int getLastMaskModified();
		int setLastMaskSaved(int p);
		int getLastMaskSaved();
		int renewMaskTime();

		int fastColorize();

		int resize();
		int updateUndoRedo();

		static MainWindow *getMainWindow(Fl_Widget *o);
		Mat *getInputImage() {printf("m_inputImage : %d\n",m_inputImage);return m_inputImage;}
		Mat *getOutputImage() {printf("m_outputImage : %d\n",m_outputImage);return m_outputImage;}
		Mat *getMask() {printf("m_mask : %d\n",m_mask);return m_mask;}
		ActionList *getActionList() {printf("m_actionList : %d\n",m_actionList);return m_actionList;}
		Fl_Menu_Bar *getMenuBar() {printf("m_menuBar : %d\n",m_menuBar);return m_menuBar;}

	protected:
		int setOutputImage(Mat &p);

		static void cb_button_loadImage(Fl_Widget *o, void *v);
		static void cb_button_loadMask(Fl_Widget *o, void *v);
		static void cb_button_saveImage(Fl_Widget *o, void *v);
		static void cb_button_saveMask(Fl_Widget *o, void *v);
		static void cb_colorChooser(Fl_Widget *o, void *v);
		static void cb_button_showViews(Fl_Widget *o, void *v);
		static void cb_button_colorize(Fl_Widget *o, void *v);
		static void cb_slider_radius(Fl_Widget *o, void *v);
		static void cb_input_radius(Fl_Widget *o, void *v);
		static void cb_button_undo(Fl_Widget *o, void *v);
		static void cb_button_redo(Fl_Widget *o, void *v);
		static void cb_button_clearMask(Fl_Widget *o, void *v);
		static void cb_slider_inputMagnifier(Fl_Widget *o, void *v);
		static void cb_input_inputMagnifier(Fl_Widget *o, void *v);
		static void cb_slider_maskMagnifier(Fl_Widget *o, void *v);
		static void cb_input_maskMagnifier(Fl_Widget *o, void *v);
		static void cb_slider_outputMagnifier(Fl_Widget *o, void *v);
		static void cb_input_outputMagnifier(Fl_Widget *o, void *v);
		static void cb_button_colors(Fl_Widget *o, void *v);
		static void cb_button_exit(Fl_Widget *o, void *v);

		static void onCanvasMouseEvent(int evt, int x, int y, int flag, void *param);
};

#endif
